/**
 * @file scififo.c
 * @author calm
 * @brief 
 * @version 1.1
 * @date 2023-03-03
 * 
 * @copyright Copyright (c) 2023
 * 
 */

#include "scififo.h"

void _scififo_append(struct scififo_t *fifo, uint8_t c) {
    fifo->data[fifo->in] = c;
    fifo->in = (fifo->in + 1) & fifo->mask;
}

/**
 * @brief 
 * @param fifo
 * @return uint16_t
 */
uint16_t _scififo_length(struct scififo_t *fifo) {
    return (fifo->in - fifo->out) & fifo->mask;
}

/**
 * @brief 
 * @param fifo
 * @param des
 * @param len
 * @return uint16_t
 */
uint16_t _scififo_copy(struct scififo_t *fifo, void *des, uint16_t len) {
    uint16_t i;
    if (len > _scififo_length(fifo)) {
        len = _scififo_length(fifo);
    }
    uint8_t *p = (uint8_t *)des;
    for (i = 0; i < len; i++) {
        *p++ = fifo->data[(fifo->out + i) & fifo->mask];
    }
    return len;
}

/**
 * @brief 
 * @param fifo 
 */
void _scififo_clear(struct scififo_t *fifo) {
    fifo->in = fifo->out;
}

/**
 * @brief 
 * 
 * @param fifo 
 * @param n 
 * @return uint16_t 
 */
uint16_t _scififo_remove(struct scififo_t *fifo, uint16_t n)
{
    uint16_t len;
    len = _scififo_length(fifo);
    if (len > n) {
        len = n;
    }
    fifo->out = (fifo->out + len) & fifo->mask;
    return len;
}

/**
 * @brief 
 * 
 * @param fifo 
 * @param n 
 * @return uint8_t 
 */
uint8_t _scififo_at(struct scififo_t *fifo, uint16_t n)
{
    return fifo->data[(fifo->out + n) & fifo->mask];
}
